package com.sloth.bear.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sloth.bear.constant.CollectType;
import com.sloth.bear.dto.entity.Category;
import com.sloth.bear.dto.entity.Collect;
import com.sloth.bear.dto.request.CollectListRequest;
import com.sloth.bear.dto.request.CreateCollectRequest;
import com.sloth.bear.dto.vo.CollectListVo;
import com.sloth.bear.mapper.CollectMapper;
import com.sloth.bear.service.CategoryService;
import com.sloth.bear.service.CollectService;
import com.sloth.bear.util.AssertUtils;
import com.sloth.bear.util.BaseHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CollectServiceImpl extends ServiceImpl<CollectMapper, Collect> implements CollectService {

    private final CategoryService categoryService;

    @Override
    public Long createCollect(CreateCollectRequest request) {
        Collect collect = BaseHelper.r2t(request, Collect.class);
        collect.setTags(JSON.toJSONString(request.getTags()));
        collect.setType(getCollectType(request));
        save(collect);
        return collect.getId();
    }

    /**
     * 新增时设置默认类型，用户也可以手动修改
     */
    private String getCollectType(CreateCollectRequest request) {
        // 如果包含b站、小红书等链接，认为是小红书类型
        if (request.getContent().contains("https://b23.tv/")) {
            return CollectType.BILIBILI.name();
        } else if (request.getContent().contains("http://xhslink.com")) {
            return CollectType.XHS.name();
        } else if (request.getContent().contains("https://www.zhihu.com/")) {
            return CollectType.ZHIHU.name();
        } else {
            return null;
        }
    }

    @Override
    public List<CollectListVo> listCollect(CollectListRequest request) {
        List<Collect> collects = list(Wrappers.<Collect>lambdaQuery()
                .isNull(Long.valueOf(-1).equals(request.getCategoryId()), Collect::getCategoryId)
                .eq(request.getCategoryId() != null && request.getCategoryId() != -1, Collect::getCategoryId, request.getCategoryId())
                .eq(Boolean.TRUE.equals(request.getIsFavorite()), Collect::getIsFavorite, true)
                .orderByDesc(Collect::getCreatedTime));
        if (CollectionUtils.isEmpty(collects)) {
            return Collections.emptyList();
        }

        Set<Long> categoryIds = collects.stream().map(Collect::getCategoryId).collect(Collectors.toSet());
        List<Category> categories = categoryService.listByIds(categoryIds);
        Map<Long, String> categoryMap = categories.stream().collect(Collectors.toMap(Category::getId, Category::getName));

        return collects.stream().map(o -> {
            CollectListVo vo = BaseHelper.r2t(o, CollectListVo.class);
            vo.setTags(JSON.parseArray(o.getTags(), String.class));
            vo.setCategoryName(categoryMap.get(o.getCategoryId()));
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public CollectListVo detailsCollect(Long id) {
        Collect collect = getEntity(id);
        return BaseHelper.r2t(collect, CollectListVo.class);
    }

    private Collect getEntity(Long id) {
        Collect collect = getById(id);
        AssertUtils.notNull(collect, "收藏不存在");
        return collect;
    }

    @Override
    public void updateCollect(Long id, CreateCollectRequest request) {
        Collect collect = getEntity(id);
        BeanUtils.copyProperties(request, collect);
        boolean result = updateById(collect);
        AssertUtils.isTrue(result, "更新失败");
    }

    @Override
    public void deleteCollect(Long id) {
        boolean result = removeById(id);
        AssertUtils.isTrue(result, "删除失败");
    }
}